home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / DIZZY / SRC / SIMDISPL.C < prev    next >
Text File  |  1991-01-08  |  9KB  |  370 lines

  1. /*
  2. >>    Dizzy 1.0    SimDisplay.c
  3. >>
  4. >>    A digital circuit simulator & design program for the X Window System
  5. >>
  6. >>    Copyright 1990 Juri Munkki, all rights reserved
  7. >>
  8. >>    Please read the included file called "DizzyDoc" for information on
  9. >>    what your rights are concerning this product.
  10. >>
  11. >>    This file contains routines that affect the way elements are displayed.
  12. */
  13.  
  14. #include "dizzy.h"
  15.  
  16. #ifdef    MACINTOSH    /*    Grid line pattern for Macintosh.    */
  17. char    GridPattern[8]={0x22,0x00,0x88,0x00,0x22,0x00,0x88,0x00};
  18. #endif
  19. char    HexDigits[]="0123456789ABCDEF"; /*    Used for hex display element.    */
  20.  
  21. /*
  22. >>    ClipEditArea sets the clipping region/rectangle to contain the editing area.
  23. >>    It also changes coordinate systems so that elements may be drawn with their
  24. >>    coordinates intact even if the display has been scrolled.
  25. */
  26. void    ClipEditArea()
  27. {
  28. #ifdef    MACINTOSH
  29.     SetPort(MyWind);
  30. #endif
  31.  
  32.     EditClipper=EditR;
  33.     OffsetRect(&EditClipper,-EditR.left+CurHeader->XOrig,-EditR.top+CurHeader->YOrig);
  34.  
  35.     SetOrigin(-EditR.left+CurHeader->XOrig,-EditR.top+CurHeader->YOrig);
  36.     ClipRect(&EditClipper);
  37. }
  38. /*
  39. >>    This routine restores default clipping and coordinate space.
  40. >>    Note that the implementation of these two routines does not
  41. >>    allow for re-entrancy. This would have complicated the design
  42. >>    of these routines unnecessarily, since re-entrancy was never
  43. >>    needed.
  44. */
  45. void    RestoreClipping()
  46. {
  47.     SetOrigin(0,0);
  48.     ClipRect(&PortRect);
  49. }
  50. /*
  51. >>    Given a pointer to an input array, an element pointer,
  52. >>    the index of the wanted input and pointers to two
  53. >>    coordinate pairs, this routine stores line endpoints
  54. >>    in (x1,y1),(x2,y2). This useful routine is used in many
  55. >>    other places in Dizzy.
  56. */
  57. int     GetConnectLine(ip,elem,index,x1,y1,x2,y2)
  58. Input    *ip;
  59. Element *elem;
  60. int     index;
  61. int     *x1,*y1,*x2,*y2;
  62. {
  63.     Element     *outelem;
  64.  
  65.     if(ip->Chip)
  66.     {    switch(elem->Type)
  67.         {    case CONN:
  68.                 *x1=elem->Body.left+4;
  69.                 *y1=elem->Body.top+4;
  70.                 break;
  71.             default:
  72.                 *x1=elem->InRect.left;
  73.                 *y1=elem->InRect.top+8+16*index;
  74.                 break;
  75.         }
  76.  
  77.         outelem=(Element *)(SimBase+ip->Chip);
  78.         switch(outelem->Type)
  79.         {    case CONN:
  80.                 *x2=outelem->Body.left+4;
  81.                 *y2=outelem->Body.top+4;
  82.                 break;
  83.             default:
  84.                 *x2=outelem->OutRect.left+8;
  85.                 *y2=outelem->OutRect.top+8+16*ip->Pin;
  86.                 break;
  87.         }
  88.         return -1;
  89.     }
  90.     else
  91.     {    return 0;
  92.     }
  93. }
  94. /*
  95. >>    ConnectLine is a simple extension of the previous
  96. >>    routine. Instead of returning the coordinates, this
  97. >>    routine just draws the line and returns.
  98. */
  99. void    ConnectLine(ip,elem,index)
  100. Input    *ip;
  101. Element *elem;
  102. int     index;
  103. {
  104.     int     x1,y1,x2,y2;
  105.     
  106.     if(GetConnectLine(ip,elem,index,&x1,&y1,&x2,&y2))
  107.     {    MoveTo(x1,y1);
  108.         LineTo(x2,y2);
  109.     }
  110. }
  111.  
  112. /*
  113. >>    Input and output rectangles contain pictures of input
  114. >>    and output pins. The pins could be drawn with a simple
  115. >>    pattern (even on the Mac), but I decided to use real
  116. >>    lines.
  117. */
  118. void    DrawLinesRect(r)
  119. Rect    *r;
  120. {
  121.     int     i;
  122.     
  123.     for(i=r->top+8;i<r->bottom;i+=16)
  124.     {    MoveTo(r->left,i);
  125.         LineTo(r->left+8,i);
  126.     }
  127. }
  128.  
  129. /*
  130. >>    CopyInsides is an extension of CopyBits and CopyPix
  131. >>    used to copy from the misc bitmap (ButtonBits on the
  132. >>    Macintosh) to the screen. ButtonBits contains bitmaps
  133. >>    for AND, OR, XOR, JK, D and RS elements.
  134. */
  135. void    CopyInsides(y1,y2,r)
  136. int     y1,y2;
  137. Rect    *r;
  138. {
  139.     Rect    src,dest;
  140.     
  141.     dest= *r;
  142.     dest.top=dest.top+((dest.bottom-dest.top)-(y2-y1))/2;
  143.     dest.bottom=dest.top+y2-y1;
  144.     dest.left+=1;
  145.     dest.right=dest.left+27;
  146.     src.left=0;
  147.     src.right=27;
  148.     src.top=y1;
  149.     src.bottom=y2;
  150. #ifdef    MACINTOSH
  151.     CopyBits(&ButtonBits,&thePort->portBits,&src,&dest,srcCopy,0L);
  152. #else
  153.     MiscPixCopy(src.left,src.top,&dest);
  154. #endif
  155.  
  156. }
  157. /*
  158. >>    UpdateSim draws the top level of the simulation. It draws all
  159. >>    the elements even if they are outside the visible area. You
  160. >>    might want to optimize this routine, if you have a slow system
  161. >>    or you want to edit really large circuits.
  162. */
  163. void    UpdateSim()
  164. {
  165.  
  166.     Element     *elem,*other;
  167.     long        offs;
  168.     int         i,j;
  169.     Input        *ip;
  170.     Rect        Inset;
  171.  
  172. #ifdef    MACINTOSH
  173.     TextFont(geneva);
  174.     TextSize(9);
  175.     PenPat(GridPattern);
  176.     EraseRect(&EditClipper);
  177.  
  178.     /*    Draw background grid on the Macintosh.    */
  179.     for(i=EditClipper.left;i<EditClipper.right+63;i+=64)
  180.     {    j=i & ~63;
  181.         MoveTo(j,EditClipper.top);
  182.         LineTo(j,EditClipper.bottom);
  183.     }
  184.     for(i=EditClipper.top;i<EditClipper.bottom+63;i+=64)
  185.     {    j=i & ~63;
  186.         MoveTo(EditClipper.left,j);
  187.         LineTo(EditClipper.right,j);
  188.     }
  189. #else
  190.     /*    Erase background with grid pattern on X */
  191.     PenGrid();
  192.     PaintRect(&EditClipper);
  193. #endif
  194.  
  195.     PenBlack();
  196.  
  197.     /*    Initialize RefCount to 0. The RefCount is used to determine if
  198.     **    an output should get the dot indicating a junction.
  199.     */
  200.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  201.     {    elem=(Element *)(SimBase+offs);
  202.         for(i=0;i<elem->Outputs;i++)
  203.         {    elem->Out[i].RefCount=0;    
  204.         }
  205.     }
  206.     
  207.     /*    Find out RefCount values and draw connecting lines. */
  208.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  209.     {    elem=(Element *)(SimBase+offs);
  210.         ip=(Input *)(&elem->Out[elem->Outputs]);
  211.         for(i=0;i<elem->Inputs;i++)
  212.         {    ConnectLine(ip,elem,i);
  213.             if(ip->Chip)
  214.             {    other=(Element *)(ip->Chip+SimBase);
  215.                 other->Out[ip->Pin].RefCount++;
  216.             }
  217.             ip++;
  218.         }
  219.     }
  220.  
  221.     /*    Draw the elements.    */
  222.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  223.     {    elem=(Element *)(SimBase+offs);
  224.         if(elem->Type!=CONN)
  225.         {    FrameRect(&elem->Body);
  226.             Inset=elem->Body;
  227.             InsetRect(&Inset,1,1);
  228.             EraseRect(&Inset);
  229.  
  230.             switch(elem->Type)
  231.             {    case AND_:    /*    Note the yuch-yuch hard-coded constant coords    */
  232.                 case NAND:    /*    This is the only place where they are used!     */
  233.                     CopyInsides(6,24,&elem->Body);
  234.                     break;
  235.                 case OR__:
  236.                 case NOR_:
  237.                     CopyInsides(24,40,&elem->Body);
  238.                     break;
  239.                 case XOR_:
  240.                 case NXOR:
  241.                     CopyInsides(40,56,&elem->Body);
  242.                     break;
  243.                 case D___:
  244.                     CopyInsides(56,84,&elem->Body);
  245.                     break;
  246.                 case RS__:
  247.                     CopyInsides(88,116,&elem->Body);
  248.                     break;
  249.                 case JK__:
  250.                     CopyInsides(116,156,&elem->Body);
  251.                     break;
  252.                 case ZERO:
  253.                     {    Rect    framer;
  254.                     
  255.                         framer=elem->Body;
  256.                         InsetRect(&framer,1,1);
  257.                         FrameRect(&framer);
  258.                         MoveTo(elem->Body.left+6,elem->Body.bottom-4);
  259.                         DrawChar('0');
  260.                     }
  261.                     break;
  262.                 case ONE_:
  263.                     {    Rect    framer;
  264.                     
  265.                         framer=elem->Body;
  266.                         InsetRect(&framer,1,1);
  267.                         FrameRect(&framer);
  268.                         MoveTo(elem->Body.left+6,elem->Body.bottom-4);
  269.                         DrawChar('1');
  270.                     }
  271.                     break;
  272.                 case INPT:
  273.                     {    char    nm[2];
  274.                     
  275.                         MoveTo(elem->Body.left+6,elem->Body.bottom-4);
  276.                         DrawChar('0'+(elem->Out[0].Data&1));
  277.                         MoveTo(elem->Body.left+3,elem->Body.bottom+9);
  278.                         nm[1]='0'+ elem->PrivData % 10;
  279.                         nm[0]='0'+ (elem->PrivData/10) % 10;
  280.                         if(nm[0]=='0') nm[0]=' ';
  281.                         DrawText(nm,0,2);
  282.                     }
  283.                     break;
  284.                 case OUTP:
  285.                     {    char    nm[2];
  286.                     
  287.                         MoveTo(elem->Body.left+6,elem->Body.bottom-4);
  288.                         DrawChar(elem->Flags & DISPLAYEDVALUE ? '1' : '0');
  289.                         MoveTo(elem->Body.left+3,elem->Body.bottom+9);
  290.                         nm[1]='0'+ elem->PrivData % 10;
  291.                         nm[0]='0'+ (elem->PrivData/10) % 10;
  292.                         if(nm[0]=='0') nm[0]=' ';
  293.                         DrawText(nm,0,2);
  294.                     }
  295.                     break;
  296.                 case HEXD:
  297.                     MoveTo(elem->Body.left+6,elem->Body.bottom-28);
  298.                     DrawChar(HexDigits[elem->PrivData]);
  299.                     break;
  300.                 case CLOK:
  301.                     MoveTo(elem->Body.left+2,elem->Body.bottom-3);
  302.                     Line(6,0);
  303.                     Line(0,-10);
  304.                     Line(5,0);
  305.                     MoveTo(elem->Body.left+2,elem->Body.bottom-4);
  306.                     DrawChar('0'+elem->PrivData);
  307.                     break;
  308.                 case CUST:
  309.                     {    TableHeader     *customhead;
  310.                         Ptr             pathstring;
  311.                     
  312.                         customhead=(TableHeader *)(elem->Inputs+(Input *)&elem->Out[elem->Outputs]);
  313.                         pathstring=(Ptr)(customhead+1);
  314.                         MoveTo(elem->Body.left+(elem->Body.right
  315.                                                 -elem->Body.left
  316.                                                 -customhead->TitleWidth)/2,
  317.                                 elem->Body.top+(elem->Body.bottom-elem->Body.top)/2+5);
  318.                         DrawText(pathstring,
  319.                                     customhead->PathLen-customhead->TitleLen,
  320.                                     customhead->TitleLen-1);
  321.                     }
  322.                     break;
  323.  
  324.             }
  325.             DrawLinesRect(&elem->InRect);
  326.             if(elem->Flags & INVERTED)    /*    Draw one inverted output pin?    */
  327.             {    Rect    round;
  328.             
  329.                 SetRect(&round, elem->OutRect.left-1,
  330.                                 elem->OutRect.top+6,
  331.                                 elem->OutRect.left+4,
  332.                                 elem->OutRect.top+11);
  333. #ifdef MACINTOSH    /*    The mac can draw ovals really quickly!                */
  334.                 FrameOval(&round);
  335. #else                /*    X is not quite as good, so use a pixmap.            */
  336.                 round.left++;
  337.                 MiscPixCopy(23,0,&round);
  338. #endif
  339.                 MoveTo(elem->OutRect.left+4,elem->OutRect.top+8);
  340.                 LineTo(elem->OutRect.left+8,elem->OutRect.top+8);
  341.             }
  342.             else
  343.             {    DrawLinesRect(&elem->OutRect);    /*    Standard output pins.    */
  344.             }
  345.  
  346.             for(i=0;i<elem->Outputs;i++)        /*    Draw dots where necessary.    */
  347.             {    if(elem->Out[i].RefCount>1)
  348.                 {    Rect    dot;
  349.                     
  350.                     dot.left=elem->OutRect.left+6;
  351.                     dot.right=dot.left+5;
  352.                     dot.top=elem->OutRect.top+i*16+6;
  353.                     dot.bottom=dot.top+5;
  354.                     PaintRect(&dot);
  355.                 }
  356.             }
  357.         }
  358.         else    /*    Draw a connector, if necessary.     */
  359.         {    Rect    dot;
  360.         
  361.             dot=elem->Body;
  362.             InsetRect(&dot,2,2);
  363.             if(elem->Out[0].RefCount != 1)
  364.                 PaintRect(&dot);
  365.             else if(ConnectorFrames)
  366.                 FrameRect(&dot);
  367.         }
  368.     }
  369. }
  370.